
import static org.junit.Assert.*;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class VendingMachineTest {

	VendingMachineItem item1,item2,item3,item4,item5;
	VendingMachine vm=new VendingMachine();
	@Before
	public void setUp() throws Exception {
		 item1=new VendingMachineItem("Skittles", 1.5);
		 item2=new VendingMachineItem("Mars", 3);
		 item3=new VendingMachineItem("Maltesers", 4);
		 item4=new VendingMachineItem("M&Ms", 4);
		 item5=new VendingMachineItem("Cadbury", 2);
		 
		 vm.addItem(item3, "C");
		 vm.addItem(item4, "D");
		 
	}

	
	
	//this should not fail and add items to the VM
	@Test
	public void test_addItem() {
		
		vm.addItem(item1, "A");  	// adding item to Slot A
		vm.addItem(item2, "B");		// adding item to Slot B
		assertEquals(item1.getName(),vm.getItem("A").getName()); //Compare Added Item with the actual item
		assertEquals(item2.getName(),vm.getItem("B").getName());

	}
	
	//This should fail and throw an exception slot already occupied 
	@Test (expected = VendingMachineException.class)
	public void test_additem_SameSlot() {
		vm.addItem(item1, "A");
		vm.addItem(item2, "A");
	
	}
	//test when removing item from empty slot
	@Test (expected = VendingMachineException.class)
	public void test_remove_SameSlot() {

		vm.removeItem("A");
		vm.removeItem("A");
		
	}

	//Tests if it returns change with a valid amount of  money
	 @Test          
	 public void testReturnChange() {                  
		 vm.addItem(item1, "A");                                    
		 vm.insertMoney(2.00); 
		 vm.makePurchase("A");       
		 assertEquals(0.5, vm.returnChange(),0);          
	}
	 
	 
	//Tests if it works when a valid amount of money is inserted
		@Test          
		public void testMakePurchase() {//
			vm.addItem(item2, "A");
			vm.insertMoney(3.00);  
			assertTrue(vm.makePurchase("A"));
		}
	//an item should be removed 
	@Test
	public void test_removeItem() {
		
		String itemName = vm.getItem("C").getName();      		// saving item name before removing it  
		VendingMachineItem removedItem = vm.removeItem("C"); 	// removing item
		assertEquals(removedItem.getName(),itemName);			//compare removed item by name to make sure it was removed 
	}
	
	//inserting and getting balance multiple times to make sure that it counts properly 
	@Test
	public void test_insertMoney_getBalance() {
		
		vm.insertMoney(5);							//insert 5 to balance
		assertEquals(5,vm.getBalance(),0.0001); 	// getting the balance to make sure it is saved
		vm.insertMoney(5);							//insert another 5 to balance
		assertEquals(10,vm.getBalance(),0.0001);	//getting the balance to make sure it adds to the previous balance
		
	}
	
	//trying to insert negative amount  this should throw invalid amount exception
	@Test (expected = VendingMachineException.class)
	public void test_insertMoney_negative() {
		vm.insertMoney(-5);							//insert -5 to balance
			assertEquals(-5,vm.getBalance(),0.0001);
	
	}
	
	//inserting and getting balance multiple times to make sure that it counts properly 
	@Test
	public void test_makePurchase_returnChange() {
		
		vm.insertMoney(5);								//insert 5$ to balance so i can buy item
		assertEquals(true,vm.makePurchase("C"));		//purchase item3 price = 4$ and make sure it returns true
		assertEquals(1,vm.getBalance(),0.0001); 		// getting the balance to make sure that i still have 1$ By Using GetBalance 
		
		assertEquals(1,vm.returnChange(),0.0001);  		//getting the return change to make sure it returns 1$ By Using return change function
	}
	
	//testing getItem when item  is already empty  
	@Test
	public void test_getItem() {
		
		vm.removeItem("C");
		assertEquals(null,vm.getItem("C"));		//purchase item3 price = 4$ and make sure it returns true
	}
	
	//Tests if it works when there is no change to return
	 @Test          
	 public void testReturnChange_noChange() {                  
		 vm.addItem(item4, "A");                                    
		 vm.insertMoney(4.00); 
		 vm.makePurchase("A");       
		 assertEquals(0.00, vm.returnChange(),0);          
	}
	 
		//Tests if it works when money less than the price is inserted
	 @Test          
	 public void testMakePurchase_lessMoney() {
		 vm.addItem(item5, "A");
		 vm.insertMoney(.50);  
		 assertFalse(vm.makePurchase("A"));          
	} 
	 
	//Tests If removes item from a slot given an invalid code 
		@Test (expected=VendingMachineException.class)
		 public void testRemoveItem_invalidCode (){
			vm.addItem(item2,"A");
			vm.removeItem("E");
			assertEquals(null,vm.getItem("E"));
		}
	//Tests if it works when money less than the price is inserted
	 @Test          
	 public void testMakePurchase_emptySlot() {
		 vm.addItem(item1, "A");
		 vm.removeItem("A");
		 vm.insertMoney(2.00);  
		 assertFalse(vm.makePurchase("A"));          
	}
	//Clearing any previous value of vmi_item after a test case completed running
	@After
	public void tearDown() throws Exception {
		vm=null;	
	}
}
